'''
Description: 
Author: Zilu
Date: 2021-11-08 13:56:00
Version: 
LastEditTime: 2021-11-08 14:26:47
LastEditors: Zilu
'''

# 高级语言都有一套 try...except...finally 的错误处理机制，python也不例外
try:
    print("try...")
    z = 10 / 0
    print('result: ', z)
except ZeroDivisionError as e:
    print('except: ', e)
finally:
    print('finally')
print('END')

# 如果没有错误，可以在except后面接一个else进行处理
try:
    print("try...")
    z = 10 / int('2')
    print('result: ', z)
except ZeroDivisionError as e:
    print('ZeroDivisionError: ', e)
except ValueError as e:
    print('ValueError: ', e)
else:
    print('no error')
finally:
    print('finally')
print('END')

# python 所有的错误都是class，都继承自BaseException。
# except不但捕获该类型的错误，连其所有的子类都一同捕获
# 所以，如确实有使用必要，先捕获子类错误，再捕获父类错误
# 常见的错误类型和继承关系：https://docs.python.org/3/library/exceptions.html#exception-hierarchy

# 错误调用栈，在栈的当前层次发生错误时，如果没有处理，会把错误往上抛，直到得到处理
# 若一直没有处理，则将错误返回给操作系统，可能会输出错误信息

# python 可以使用logging模块记录错误
import logging

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)

main()
print('END')

# 通过配置，logging还可以把错误记录到日志文件里，方便事后排查

# 使用 raise 可以抛出错误，也可以自定义错误
# raise 语句如果不带参数，就将当前错误原样抛出
def foo(s):
    n = int(s)
    if n==0:
        raise ValueError('invalid value: %s' % s)
    return 10 / n

def bar():
    try:
        foo('0')
    except ValueError as e:
        print('ValueError!')
        raise

bar()





